#!/bin/bash
###############################################################################
#       脚本名称: log_sanitizer.sh
#       功能描述: 数据脱敏模块,自动识别并脱敏敏感信息
#       作者: 林再来
#       日期: 2025-10-14
#       版本: 1.0
#       功能:
#           1、自动识别常见敏感信息(密码、手机号、邮箱等)
#           2、支持自定义脱敏规则
#           3、支持多种脱敏策略(掩码、部分显示、完全隐藏)
#           4、高性能正则匹配
#       依赖(插件/命令):
#           sed(文本处理)
###############################################################################

# 防止重复加载
[[ -n "${_LOG_SANITIZER_LOADED:-}" ]] && return 0
readonly _LOG_SANITIZER_LOADED=1

#-----------------------------------------------------------------------------
# 全局变量
#-----------------------------------------------------------------------------
# 自定义脱敏规则
declare -gA _LOG_SANITIZER_RULES
# 是否启用脱敏
declare -g _LOG_SANITIZER_ENABLED="false"

#-----------------------------------------------------------------------------
# 内置脱敏规则
#-----------------------------------------------------------------------------
# 密码规则
readonly SANITIZE_PATTERN_PASSWORD='(password|pwd|passwd|pass|secret|token|api[_-]?key)([=:][[:space:]]*)([^&[:space:],;]+)'
readonly SANITIZE_REPLACE_PASSWORD='\1\2****'

# 手机号规则(中国)
readonly SANITIZE_PATTERN_PHONE='1[3-9]\d{9}'
readonly SANITIZE_REPLACE_PHONE='****'

# 邮箱规则
readonly SANITIZE_PATTERN_EMAIL='([a-zA-Z0-9._%+-]+)@([a-zA-Z0-9.-]+\.[a-zA-Z]{2,})'
readonly SANITIZE_REPLACE_EMAIL='***@\2'

# 身份证号规则(中国)
readonly SANITIZE_PATTERN_IDCARD='[1-9]\d{5}(19|20)\d{2}(0[1-9]|1[0-2])(0[1-9]|[12]\d|3[01])\d{3}[\dXx]'
readonly SANITIZE_REPLACE_IDCARD='****'

# 银行卡号规则
readonly SANITIZE_PATTERN_BANKCARD='[1-9]\d{15,18}'
readonly SANITIZE_REPLACE_BANKCARD='****'

# IP地址规则(可选)
readonly SANITIZE_PATTERN_IP='\b\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\b'
readonly SANITIZE_REPLACE_IP='*.*.*.*'

#-----------------------------------------------------------------------------
# 函数: 初始化脱敏模块
# 参数: $1 - 是否启用(true/false,可选,默认false)
# 返回: 0-成功
#-----------------------------------------------------------------------------
function _log_sanitizer_init() {
    local enabled="${1:-false}"
    
    _LOG_SANITIZER_ENABLED="$enabled"
    
    # 清空自定义规则
    _LOG_SANITIZER_RULES=()
    
    return 0
}

#-----------------------------------------------------------------------------
# 函数: 启用脱敏
# 参数: 无
# 返回: 0-成功
#-----------------------------------------------------------------------------
function log_sanitizer_enable() {
    _LOG_SANITIZER_ENABLED="true"
    return 0
}

#-----------------------------------------------------------------------------
# 函数: 禁用脱敏
# 参数: 无
# 返回: 0-成功
#-----------------------------------------------------------------------------
function log_sanitizer_disable() {
    _LOG_SANITIZER_ENABLED="false"
    return 0
}

#-----------------------------------------------------------------------------
# 函数: 检查是否启用脱敏
# 参数: 无
# 返回: 0-已启用, 1-未启用
#-----------------------------------------------------------------------------
function log_sanitizer_is_enabled() {
    [[ "$_LOG_SANITIZER_ENABLED" == "true" ]]
}

#-----------------------------------------------------------------------------
# 函数: 添加自定义脱敏规则
# 参数: $1 - 规则名称
#       $2 - 正则模式
#       $3 - 替换字符串
# 返回: 0-成功
#-----------------------------------------------------------------------------
function log_sanitizer_add_rule() {
    local rule_name="$1"
    local pattern="$2"
    local replacement="$3"
    
    _LOG_SANITIZER_RULES["${rule_name}_pattern"]="$pattern"
    _LOG_SANITIZER_RULES["${rule_name}_replacement"]="$replacement"
    
    return 0
}

#-----------------------------------------------------------------------------
# 函数: 删除自定义脱敏规则
# 参数: $1 - 规则名称
# 返回: 0-成功
#-----------------------------------------------------------------------------
function log_sanitizer_remove_rule() {
    local rule_name="$1"
    
    unset _LOG_SANITIZER_RULES["${rule_name}_pattern"]
    unset _LOG_SANITIZER_RULES["${rule_name}_replacement"]
    
    return 0
}

#-----------------------------------------------------------------------------
# 函数: 脱敏密码信息
# 参数: $1 - 原始文本
# 返回: 输出脱敏后的文本
#-----------------------------------------------------------------------------
function _sanitize_password() {
    local text="$1"
    
    # 使用sed进行替换(不区分大小写)
    echo "$text" | sed -E "s/${SANITIZE_PATTERN_PASSWORD}/${SANITIZE_REPLACE_PASSWORD}/gI"
}

#-----------------------------------------------------------------------------
# 函数: 脱敏手机号
# 参数: $1 - 原始文本
# 返回: 输出脱敏后的文本
#-----------------------------------------------------------------------------
function _sanitize_phone() {
    local text="$1"
    
    # 保留前3位和后4位
    echo "$text" | sed -E "s/(1[3-9][0-9])([0-9]{4})([0-9]{4})/\1****\3/g"
}

#-----------------------------------------------------------------------------
# 函数: 脱敏邮箱
# 参数: $1 - 原始文本
# 返回: 输出脱敏后的文本
#-----------------------------------------------------------------------------
function _sanitize_email() {
    local text="$1"
    
    echo "$text" | sed -E "s/${SANITIZE_PATTERN_EMAIL}/${SANITIZE_REPLACE_EMAIL}/g"
}

#-----------------------------------------------------------------------------
# 函数: 脱敏身份证号
# 参数: $1 - 原始文本
# 返回: 输出脱敏后的文本
#-----------------------------------------------------------------------------
function _sanitize_idcard() {
    local text="$1"
    
    # 保留前6位和后4位
    echo "$text" | sed -E "s/([1-9][0-9]{5})(19|20)([0-9]{2})(0[1-9]|1[0-2])(0[1-9]|[12][0-9]|3[01])([0-9]{3}[0-9Xx])/\1********\6/g"
}

#-----------------------------------------------------------------------------
# 函数: 脱敏银行卡号
# 参数: $1 - 原始文本
# 返回: 输出脱敏后的文本
#-----------------------------------------------------------------------------
function _sanitize_bankcard() {
    local text="$1"
    
    # 保留前4位和后4位
    echo "$text" | sed -E "s/([1-9][0-9]{3})([0-9]{8,10})([0-9]{4})/\1****\3/g"
}

#-----------------------------------------------------------------------------
# 函数: 脱敏IP地址(可选)
# 参数: $1 - 原始文本
# 返回: 输出脱敏后的文本
#-----------------------------------------------------------------------------
function _sanitize_ip() {
    local text="$1"
    
    # 保留前两段
    echo "$text" | sed -E "s/([0-9]{1,3}\.[0-9]{1,3})\.[0-9]{1,3}\.[0-9]{1,3}/\1.*.*/"
}

#-----------------------------------------------------------------------------
# 函数: 执行所有内置脱敏规则
# 参数: $1 - 原始文本
# 返回: 输出脱敏后的文本
#-----------------------------------------------------------------------------
function _sanitize_builtin() {
    local text="$1"
    
    # 依次应用所有内置规则
    text=$(_sanitize_password "$text")
    text=$(_sanitize_phone "$text")
    text=$(_sanitize_email "$text")
    text=$(_sanitize_idcard "$text")
    text=$(_sanitize_bankcard "$text")
    # 可选：IP脱敏(注释掉如果不需要)
    # text=$(_sanitize_ip "$text")
    
    echo "$text"
}

#-----------------------------------------------------------------------------
# 函数: 执行自定义脱敏规则
# 参数: $1 - 原始文本
# 返回: 输出脱敏后的文本
#-----------------------------------------------------------------------------
function _sanitize_custom() {
    local text="$1"
    
    # 遍历所有自定义规则
    for rule_name in "${!_LOG_SANITIZER_RULES[@]}"; do
        if [[ "$rule_name" == *"_pattern" ]]; then
            local base_name="${rule_name%_pattern}"
            local pattern="${_LOG_SANITIZER_RULES[${base_name}_pattern]}"
            local replacement="${_LOG_SANITIZER_RULES[${base_name}_replacement]}"
            
            text=$(echo "$text" | sed -E "s/${pattern}/${replacement}/g")
        fi
    done
    
    echo "$text"
}

#-----------------------------------------------------------------------------
# 函数: 脱敏处理(主入口)
# 参数: $1 - 原始文本
# 返回: 输出脱敏后的文本
#-----------------------------------------------------------------------------
function log_sanitize() {
    local text="$1"
    
    # 检查是否启用
    if ! log_sanitizer_is_enabled; then
        echo "$text"
        return 0
    fi
    
    # 应用内置规则
    text=$(_sanitize_builtin "$text")
    
    # 应用自定义规则
    text=$(_sanitize_custom "$text")
    
    echo "$text"
}

#-----------------------------------------------------------------------------
# 函数: 列出所有脱敏规则
# 参数: 无
# 返回: 无
#-----------------------------------------------------------------------------
function log_sanitizer_list_rules() {
    echo "=== 内置脱敏规则 ==="
    echo "  1. 密码(password/pwd/token/api_key)"
    echo "  2. 手机号(中国,保留前3后4)"
    echo "  3. 邮箱(保留域名)"
    echo "  4. 身份证号(保留前6后4)"
    echo "  5. 银行卡号(保留前4后4)"
    
    echo ""
    echo "=== 自定义脱敏规则 ==="
    
    if [[ ${#_LOG_SANITIZER_RULES[@]} -eq 0 ]]; then
        echo "  (无)"
        return 0
    fi
    
    local count=0
    for rule_name in "${!_LOG_SANITIZER_RULES[@]}"; do
        if [[ "$rule_name" == *"_pattern" ]]; then
            ((count++))
            local base_name="${rule_name%_pattern}"
            local pattern="${_LOG_SANITIZER_RULES[${base_name}_pattern]}"
            local replacement="${_LOG_SANITIZER_RULES[${base_name}_replacement]}"
            echo "  $count. $base_name"
            echo "     Pattern: $pattern"
            echo "     Replacement: $replacement"
        fi
    done
}

#-----------------------------------------------------------------------------
# 测试函数
#-----------------------------------------------------------------------------
function _log_sanitizer_test() {
    echo "=== 数据脱敏模块测试 ==="
    
    echo ""
    echo "1. 初始化并启用脱敏:"
    _log_sanitizer_init "true"
    echo "  ✓ 脱敏已启用: $(log_sanitizer_is_enabled && echo 是 || echo 否)"
    
    echo ""
    echo "2. 测试密码脱敏:"
    local test_password="用户登录: username=admin password=secret123 token=abc123xyz"
    echo "  原文: $test_password"
    echo "  脱敏: $(log_sanitize "$test_password")"
    
    echo ""
    echo "3. 测试手机号脱敏:"
    local test_phone="联系方式: 13812345678, 手机: 18900001111"
    echo "  原文: $test_phone"
    echo "  脱敏: $(log_sanitize "$test_phone")"
    
    echo ""
    echo "4. 测试邮箱脱敏:"
    local test_email="Email: user@example.com, admin@test.org"
    echo "  原文: $test_email"
    echo "  脱敏: $(log_sanitize "$test_email")"
    
    echo ""
    echo "5. 测试身份证号脱敏:"
    local test_idcard="身份证: 350221199001013519"
    echo "  原文: $test_idcard"
    echo "  脱敏: $(log_sanitize "$test_idcard")"
    
    echo ""
    echo "6. 测试银行卡号脱敏:"
    local test_bankcard="银行卡: 6225760012347022"
    echo "  原文: $test_bankcard"
    echo "  脱敏: $(log_sanitize "$test_bankcard")"
    
    echo ""
    echo "7. 添加自定义脱敏规则:"
    log_sanitizer_add_rule "custom_code" "CODE-\d{6}" "CODE-******"
    local test_custom="订单号: CODE-123456"
    echo "  原文: $test_custom"
    echo "  脱敏: $(log_sanitize "$test_custom")"
    
    echo ""
    echo "8. 列出所有脱敏规则:"
    log_sanitizer_list_rules | sed 's/^/  /'
    
    echo ""
    echo "9. 禁用脱敏测试:"
    log_sanitizer_disable
    echo "  脱敏已禁用,原文输出: $(log_sanitize "$test_password")"
}

# 如果直接执行此脚本,运行测试
if [[ "${BASH_SOURCE[0]}" == "${0}" ]]; then
    _log_sanitizer_test
fi

